home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * B G _ G R A F 1 . C
- * A graphics module for the backgammon playing program BG.C.
- * This version 30th January 1993
- *
- *
-
- +--------------------+--------+ Here is the screen layout.
- | | dice |
- | | area |
- | board +--------+ The dice area must always
- | | face | have a 2-1 aspect ratio, and the
- | area | area | text area must always have SIDE_ROWS
- | +--------+ and SIDE_COLS. The logo area is
- | | | a buffer zone. The help area holds
- | | text | one line of text.
- +--------------------+ area |
- | help area | |
- +--------------------+--------+ The board area is
- further divided into a grid of 14 by 12, which is used as the basis for
- drawing the points and the pieces, see BG_GRAF2.C.
-
- *****************************************************************************/
-
- #include "comp.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <bios.h>
- #include <conio.h>
- #include <math.h>
- #include "bg.h"
-
- /****************************************************************************/
- /* Local defines ... */
-
- Disp_Cfg_t Disp_Cfg ; /* How the hardware has come to me */
-
- Screen_Const_t Grafs ; /* How I have divided the screen areas */
-
- /* Here is the dice graphics structure */
- static struct {
- short Area_Wide ; /* Pixel sizeof entire... */
- short Area_High ; /* ...area, inclusive */
- short Wide,High ; /* Actual size of a single dice */
- short Dot_Wide ; /* Size of a dot... */
- short Dot_High ; /* ...on a face */
- short Dice1_X,Dice2_X ; /* X position of the two die */
- short X,Y ; /* Absoulte screen position of dice area */
- short T_Row,T_Col ; /* A row of text below the dice, defined on the
- text grid, to show dice as a row of numbers */
- } Dice_Gr ;
-
- boolean Force_BW = FALSE ; /* Force a black&white display from command line */
-
- /****************************************************************************/
- /**** LOCAL PRIVATE FUNCTIONS ****/
-
- static void Init_Text_Fields (void) ;
- static void Init_Dice_Grafs (void) ;
-
- /****************************************************************************/
-
- void Init_Graphics (void)
- /*
- PURPOSE: To initialise the screen to graphics mode and to set up
- the various graphics structures used throughout the
- program
- */
- {
- {
- #define CGATEST 0
- #define EGATEST 0
- #define IBMTEST 0
- int G_Driver,G_Mode,G_Error ;
- #if CGATEST
- G_Driver = CGA ;
- G_Mode = CGAHI ;
- printf ("\nWARNING: CGATEST:") ; (void)getch () ;
- #elif EGATEST
- G_Driver = EGA ;
- G_Mode = EGAHI ;
- printf ("\nWARNING: EGATEST:") ; (void)getch () ;
- #elif IBMTEST
- G_Driver = IBM8514 ;
- G_Mode = 0 ;
- printf ("\nWARNING: IBMTEST:") ; (void)getch () ;
- #else
- G_Driver = DETECT ;
- #endif
-
- initgraph (&G_Driver,&G_Mode,"C:\\BORLANDC\\BGI") ;
-
- G_Error = graphresult () ;
- if (G_Error != grOk) {
- printf ("\nError %s",grapherrormsg(G_Error));
- (void)getch () ;
- exit (1) ;
- } else if (G_Driver == CGA) {
- closegraph () ;
- printf ("\nERROR: This program requires an EGA or a VGA display.") ;
- exit (1) ;
- }
- Disp_Cfg.Colour = TRUE ;
- switch (G_Driver) {
- case HERCMONOHI :
- case EGAMONO :
- Disp_Cfg.Colour = FALSE ;
- break ;
- case VGA:
- setgraphmode (VGAMED) ;
- break ;
- case IBM8514:
- setgraphmode (0) ;
- break ;
- }
- if (Force_BW) {
- Disp_Cfg.Colour = FALSE ;
- }
- }
-
- Get_Display_Config (&Disp_Cfg) ;
- Init_Text_Fields () ; /* The other fields made to fit with text */
-
- Grafs.Dice_Area_Y = 1 ;
- Grafs.Dice_Area_X = Grafs.Text_X ;
-
- Init_Dice_Grafs () ;
- Init_And_Draw_Logo () ;
-
- Grafs.Board_X = 1 ;
- Grafs.Board_Y = 1 ;
- Grafs.Board_Wide = Disp_Cfg.X_Pixels - Grafs.Text_Wide - (2*Disp_Cfg.Char_Wide) ;
- Grafs.Board_High = Disp_Cfg.Y_Pixels - (Disp_Cfg.Char_High*2) - 2 ;
- Grafs.Help_Y = Grafs.Board_High ;
-
- Grafs.Grid_Wide = Grafs.Board_Wide / GRID_COLS ;
- Grafs.Grid_High = Grafs.Board_High / GRID_ROWS ;
-
- Grafs.Board_Wide = GRID_COLS * Grafs.Grid_Wide ; /* Now they are ... */
- Grafs.Board_High = GRID_ROWS * Grafs.Grid_High ; /* ...exact multiples. */
-
- Grafs.Unit_Wide = Grafs.Grid_Wide-4 ;
- Grafs.Unit_High = Grafs.Grid_High-4 ;
-
- Get_Grid_Corner (&Grafs.Double_X,&Grafs.Double_Y,BAR_COL,DOUBLE_ROW) ;
- }
-
- /****************************************************************************/
-
- static void Init_Text_Fields (void)
- /*
- PURPOSE: To initialise the text fields so that there is a block of text
- to the left-bottom of TEXT_ROWS high and TEXT_COLS wide. We also init
- the help text area so that there is a single row of text available.
- The positions are based on a character sized matrix over the whole screen
- because some compilers and or devices cannot put text at abitrary x-y
- positions.
- */
- {
- Grafs.Text_Wide = SIDE_COLS*Disp_Cfg.Char_Wide ;
- Grafs.Text_High = SIDE_ROWS*Disp_Cfg.Char_High ;
- Grafs.Text_X = Disp_Cfg.X_Pixels - Grafs.Text_Wide ;
- Grafs.Text_Y = Disp_Cfg.Y_Pixels - Grafs.Text_High ;
- Grafs.Help_X = 0 ;
- Grafs.Help_Y = (Disp_Cfg.Y_Pixels/Disp_Cfg.Char_High) * Disp_Cfg.Char_High ;
- Grafs.Help_Wide = Disp_Cfg.X_Pixels - Grafs.Text_Wide ;
- Grafs.Help_Cols = Disp_Cfg.Text_Cols - SIDE_COLS ;
- }
-
- /****************************************************************************/
-
- void Get_Grid_Corner (short* Grid_X, short* Grid_Y,
- short Grid_Col, short Grid_Row)
- /*
- PURPOSE: To return in Grid_X, Grid_Y the absolute coords of the
- top left of the Grid_Row,Grid_Col square.
- */
- {
- (*Grid_X) = Grafs.Board_X + ((Grid_Col*Grafs.Board_Wide)/GRID_COLS) ;
- (*Grid_Y) = Grafs.Board_Y + ((Grid_Row*Grafs.Board_High)/GRID_ROWS) ;
- }
-
- /**************************************************************************/
-
- void Get_Grid_Center (short* Grid_X, short* Grid_Y,
- short Grid_Col, short Grid_Row)
- /*
- PURPOSE: To return in Grid_X, Grid_Y the absolute coords of the
- middle of the Grid_Row,Grid_Col square.
- */
- {
- Get_Grid_Corner (Grid_X,Grid_Y,Grid_Col,Grid_Row) ;
- (*Grid_X) = (*Grid_X) + (Grafs.Grid_Wide/2) ;
- (*Grid_Y) = (*Grid_Y) + (Grafs.Grid_High/2) ;
- }
-
- /**************************************************************************/
-
- void Draw_Dice_Pair (Dice_t* Pair, Player_t Player)
- /*
- PURPOSE: To show the two dice with the two values.
- */
- {
- Draw_Die (Pair->Values[0],1,Player) ;
- Draw_Die (Pair->Values[1],2,Player) ;
- }
-
- /**************************************************************************/
-
- /* The following array is initialised to the positions of dots for the
- 6 values of the dice faces when the face is divided into a 10 by 10 grid */
- static short Dot_Pos_Arr [7][6][2] =
- {{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* Value0 has no face */
- {{5,5},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* Single dot in centre */
- {{2,5},{8,5},{0,0},{0,0},{0,0},{0,0}}, /* Two dots */
- {{2,5},{8,5},{5,5},{0,0},{0,0},{0,0}}, /* Three dots */
- {{2,2},{8,8},{2,8},{8,2},{0,0},{0,0}}, /* Four dots */
- {{2,2},{8,8},{2,8},{8,2},{5,5},{0,0}}, /* Five dots */
- {{2,2},{5,2},{8,2},{2,8},{5,8},{8,8}}}; /* Five dots */
- /* Later these values will be recalculated to make them the top left
- corner of the dots. */
-
- static void Init_Dice_Grafs (void)
- /*
- PURPOSE: To set up the dice graphic variables.
- NOTES : 1) The basic area is derived starting from Text_Wide.
- 2) The two dice are arranged as a horizontal pair, with
- separated one from the other by 2 DICE_MARGINS and
- from the edge of the area by a single DICE_MARGIN.
- */
- {
- #define DICE_MARGIN 4
- short y,v,dot ;
- Dice_Gr.Area_Wide = Grafs.Text_Wide ;
- Dice_Gr.X = Grafs.Text_X ;
- Dice_Gr.Wide = (Dice_Gr.Area_Wide - (4*DICE_MARGIN)) / 2 ;
- Dice_Gr.High = (Dice_Gr.Wide * Disp_Cfg.Aspect_V) / Disp_Cfg.Aspect_H ;
- Dice_Gr.Area_High = Dice_Gr.High +
- ((2*(DICE_MARGIN*Disp_Cfg.Aspect_V))/Disp_Cfg.Aspect_H) ;
-
- y = Dice_Gr.Area_High + (2*Disp_Cfg.Char_High) ;
- Dice_Gr.T_Row = (y / Disp_Cfg.Char_High) - 1 ;
- Dice_Gr.Area_High = Dice_Gr.Area_High + (2*Disp_Cfg.Char_High) ;
-
- Dice_Gr.T_Col = Disp_Cfg.Text_Cols - SIDE_COLS ;
-
- Dice_Gr.Dice1_X = Grafs.Dice_Area_X + DICE_MARGIN ;
- Dice_Gr.Dice2_X = Grafs.Dice_Area_X + (3*DICE_MARGIN) + Dice_Gr.Wide ;
- Dice_Gr.Y = Grafs.Dice_Area_Y +
- ((DICE_MARGIN*Disp_Cfg.Aspect_V)/Disp_Cfg.Aspect_H) ;
- Dice_Gr.Dot_Wide = Dice_Gr.Wide / 5 ;
- Dice_Gr.Dot_High = Dice_Gr.High / 5 ;
-
- /* Setup positions for drawing dots */
- for (v = 1 ; v <= 6 ; v++) {
- for (dot = 0 ; dot < 6 ; dot++) {
- Dot_Pos_Arr[v][dot][XI] = (Dot_Pos_Arr[v][dot][XI]*Dice_Gr.Wide)/10 ;
- Dot_Pos_Arr[v][dot][XI] = Dot_Pos_Arr[v][dot][XI] -
- (Dice_Gr.Dot_Wide/2) ;
- Dot_Pos_Arr[v][dot][YI] = (Dot_Pos_Arr[v][dot][YI]*Dice_Gr.High)/10 ;
- Dot_Pos_Arr[v][dot][YI] = Dot_Pos_Arr[v][dot][YI] -
- (Dice_Gr.Dot_High/2);
- }
- }
- }
-
- /****************************************************************************/
-
- void Draw_Die (short Value, short Dice_Num, Player_t Player)
- /*
- PURPOSE: To draw a single die of Value. X_Pos is determined by Dice_Num
- which should be 1 or 2.
- */
- {
- short dot,Fill_Color,Dot_Color,X_Pos ;
-
- if ((Value < 1) || (Value > 6)) {
- printf ("\nBad value in Draw_Die (%d,%d,%d)",Value,Dice_Num,Player) ;
- Error_Exit ("\nBad Value in Draw_Die") ;
- }
-
- if (Disp_Cfg.Colour) {
- if (Player == BLACK_PLAYER) {
- Fill_Color = LIGHTRED ;
- Dot_Color = WHITE ;
- } else {
- Fill_Color = WHITE ;
- Dot_Color = RED ;
- }
- } else {
- if (Player == BLACK_PLAYER) {
- Fill_Color = BLACK ;
- Dot_Color = WHITE ;
- } else {
- Fill_Color = WHITE ;
- Dot_Color = BLACK ;
- }
- }
- if (Dice_Num == 1) {
- X_Pos = Dice_Gr.Dice1_X ;
- } else {
- X_Pos = Dice_Gr.Dice2_X ;
- }
-
- Fill_Rect (X_Pos,Dice_Gr.Y,Dice_Gr.Wide,Dice_Gr.High,Fill_Color) ;
- Draw_Rect (X_Pos,Dice_Gr.Y,Dice_Gr.Wide,Dice_Gr.High,WHITE) ;
-
- /* draw the dots... */
- for (dot = 0 ; dot < Value ; dot++) {
- Fill_Rect (X_Pos + Dot_Pos_Arr [Value][dot][XI],
- Dice_Gr.Y + Dot_Pos_Arr [Value][dot][YI],
- Dice_Gr.Dot_Wide,Dice_Gr.Dot_High,Dot_Color) ;
- }
- }
-
- /**************************************************************************/
-
- void Clear_Die (short Dice_Num)
- /*
- PURPOSE: To clear the area of a single die of X_Pos is determined
- by Dice_Num which should be 1 or 2.
- */
- {
- short X_Pos ;
-
- if (Dice_Num == 1) {
- X_Pos = Dice_Gr.Dice1_X ;
- } else {
- X_Pos = Dice_Gr.Dice2_X ;
- }
-
- Fill_Rect (X_Pos,Dice_Gr.Y,Dice_Gr.Wide,Dice_Gr.High+1,BLACK) ;
- }
-
- /**************************************************************************/
-
- void Draw_Stats (void)
- /*
- PURPOSE: To draw the current statistics in the statistics box
- */
- {
- extern Stats_t Statistics[2] ;
- extern int Target_Score ;
- short p ;
-
- Print_Message (ID_MSG) ;
- Print_Message (TOTAL_MSG) ;
- Print_Message (DOUBLE_MSG) ;
- Print_Message (POINTS_MSG) ;
-
- for (p = BLACK_PLAYER ; p < N_PLAYERS ; p++) {
- Side_Number (TOTALN_ROW, (ushort)(p*NUM_WIDE),
- Statistics[p].Total,NUM_WIDE,15) ;
- Side_Number (DOUBN_ROW, (ushort)(p*NUM_WIDE),
- Statistics[p].Doubles,NUM_WIDE,15) ;
- Side_Number (POINTSN_ROW, (ushort)(p*NUM_WIDE),
- Statistics[p].Games_Won,NUM_WIDE,15) ;
- Print_Message (PLAY_TO_MSG) ;
- Side_Number (TARGETN_ROW,(ushort)(p*NUM_WIDE),
- Target_Score,NUM_WIDE,15) ;
- }
- }
-
- /**************************************************************************/
-
- void Graf_Number (ushort Row, ushort Col, ushort Number,
- ushort F_Size, ushort Color)
- /*
- PURPOSE: To print the number at the Row,Col on the graphics screen.
- */
- {
- char Num_Str [16] ;
- ushort c ;
-
- /* Blank area for string */
- for (c = 0 ; c < F_Size ; c++) {
- Graf_Text (Row,Col+c," ",Color) ;
- }
-
- (void)itoa (Number,Num_Str,10) ;
- Graf_Text (Row,Col,Num_Str,Color) ;
- }
-
- /**************************************************************************/
-
- void Side_Number (ushort Row, ushort Col, ushort Number,
- ushort F_Size, ushort Color)
- /*
- PURPOSE: To print the number at the Row,Col of the side text in the
- specified field size and color.
- */
- {
- char Num_Str [16] ;
- ushort c ;
-
- /* Blank area for string */
- for (c = 0 ; c < F_Size ; c++) {
- Side_Text (Row,Col+c," ",Color) ;
- }
-
- (void)itoa (Number,Num_Str,10) ;
- Side_Text (Row,Col,Num_Str,Color) ;
- }
-
- /**************************************************************************/
-
- void Init_And_Draw_Logo (void)
- /*
- PURPOSE: To draw the largest logo in the center of the space left for
- that purpose. The space is what remains after the text and
- dice areas have been initialised.
- */
- {
- short Wide,High ;
-
- /* Initialise the fields telling us the area available */
- Grafs.Logo_Y = Dice_Gr.Area_High + 2 ; /* 2 dividing lines */
- Grafs.Logo_X = Grafs.Text_X ;
- Grafs.Logo_High = Disp_Cfg.Y_Pixels - Dice_Gr.Area_High -
- Grafs.Text_High - 4 ; /* 4 dividing lines */
- if (Grafs.Logo_High <= 5) {
- printf ("\nGrafs.Logo_High too small: %d.",Grafs.Logo_High) ;
- Error_Exit ("Logo_High too small") ;
- }
- Grafs.Logo_Wide = Grafs.Text_Wide ;
-
- if (Grafs.Logo_Wide > ((Grafs.Logo_High*Disp_Cfg.Aspect_H)/Disp_Cfg.Aspect_V)) {
- /* Area is wider than high, logo square based on height */
- High = Grafs.Logo_High-2 ;
- Wide = (High*Disp_Cfg.Aspect_H)/Disp_Cfg.Aspect_V ;
- } else {
- /* Area is higher than wide, logo square based on width */
- Wide = Grafs.Logo_Wide-2 ;
- High = (Grafs.Logo_Wide*Disp_Cfg.Aspect_V)/Disp_Cfg.Aspect_H ;
- }
- /* Now Wide and High should draw a square on the screen */
-
- Grafs.Logo_X = ((Grafs.Logo_Wide - Wide) / 2) + Grafs.Logo_X + 1 ;
- Grafs.Logo_Y = ((Grafs.Logo_High - High) / 2) + Grafs.Logo_Y + 1;
- Grafs.Logo_Wide = Wide ;
- Grafs.Logo_High = High ;
- Grafs.Logo_Center = Grafs.Logo_X + (Grafs.Logo_Wide/2) ;
- }
-
- /**************************************************************************/
-
- void Clear_Logo_Area (void)
- /*
- PURPOSE: To clear the logo area to black.
- */
- {
- Fill_Rect (Grafs.Logo_X,Grafs.Logo_Y,
- Grafs.Logo_Wide,Grafs.Logo_High,BLACK) ;
- }
-
- /**************************************************************************/
-
- boolean Even (short Number)
- {
- if (((Number/2)*2) == Number) {
- return (TRUE) ;
- } else {
- return (FALSE) ;
- }
- }
-
- /**************************************************************************/
-
- void Show_Dice_List (Dice_t* Dice)
- /*
- PURPOSE: To list the dice (0..4) as some digits below the drawing of the
- dice.
- */
- {
- short i ;
-
- for (i = 0 ; i < SIDE_COLS ; i++ ) {
- Graf_Text (Dice_Gr.T_Row, Dice_Gr.T_Col+i,"-",WHITE) ;
- }
-
- for (i = 0 ; i < Dice->N_Vals ; i++) {
- Graf_Number (Dice_Gr.T_Row,Dice_Gr.T_Col+(2*i)+2,
- Dice->Values[i],1,WHITE) ;
- }
- }
-
- /***************************************************************************/
-